class Solution {
public:
    int margin[4][61];
    bool isConnect[61][61];
    bool isPrintable(vector<vector<int>>& targetGrid) {
        int m = targetGrid.size();
        int n = targetGrid[0].size();
        memset(margin, -1, sizeof(margin));
        memset(isConnect, false, sizeof(isConnect));

        unordered_map<int,vector<int> > edges;
        unordered_map<int,int> indeg;
     //   indeg[0] = 0;
        
        for(int i = 0; i < m; i ++){
            for(int j = 0; j < n; j ++){
                int curColor = targetGrid[i][j];
                margin[0][curColor] = margin[0][curColor] == -1 ? i : min(margin[0][curColor], i);
                margin[1][curColor] = margin[1][curColor] == -1 ? i : max(margin[1][curColor], i);
                margin[2][curColor] = margin[2][curColor] == -1 ? j : min(margin[2][curColor], j);
                margin[3][curColor] = margin[3][curColor] == -1 ? j : max(margin[3][curColor], j);
            }
        }

        
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){
                int curColor = targetGrid[i][j];
                if(!indeg.count(curColor)){
                    indeg[curColor] = 0;
                }
                for(int color = 1;color <= 60;color++){
                    if(color != curColor && !isConnect[color][curColor]
                    && margin[0][color] <= i && i <= margin[1][color]
                    && margin[2][color] <= j && j <= margin[3][color]){
                        isConnect[color][curColor] = true;
                        edges[color].push_back(curColor);
                        indeg[curColor]++;
                    }  
                }
            }
        }
        
        queue<int> que;
        for(auto& u : indeg){
            if(u.second == 0){
                que.push(u.first);
            }
        }
        
        vector<int> ret;
        while(!que.empty()){
            int u = que.front();
            que.pop();
            ret.push_back(u);
            for(int& v : edges[u]){
                --indeg[v];
                if(indeg[v] == 0){
                    que.push(v);
                }
            }
        }
        for(auto& u : indeg){
            if(u.second > 0){
                return false;
            }
        }
        return true;
    }
};
